function[U B V] = predictor(X1, X2, data_ls, stepSize, lambda, Prediction_before)

%
% Given X1 and X2 predict X = UBV^T
%

p1 = size(X1.U, 2);
p2 = size(X2.U, 2);


if p1 == p2
   
      L = chol(X2.B);
      eta.B = L'*logm(L'\X1.B/L)*L;
      eta.U = X1.U - X2.U;
      eta.V = X1.V - X2.V;        
      
      ProjDir = project_horizontal_space(eta, X2); % Project from Euclidean space Horizontal space

      ProjDir.U = -ProjDir.U;
      ProjDir.B = -ProjDir.B;
      ProjDir.V = -ProjDir.V;
      
      grad = functions_matrix_completion_polar('grad_f', X2, [], data_ls, []);
      
      innerproduct = trace(grad.U'*ProjDir.U) + trace(grad.V'*ProjDir.V) + trace((X2.B\grad.B)*(X2.B\ProjDir.B));


      fprintf('..... Warm restart: %.5e\n', Prediction_before);
      
     
      U = uf(X2.U + stepSize*ProjDir.U);
      V = uf(X2.V + stepSize*ProjDir.V);
      B = L'*expm(L'\(stepSize*ProjDir.B)/L)*L; 
      test_model.U = U; test_model.B = B; test_model.V = V; test_model.lambda = lambda;
      Prediction_after = functions_matrix_completion_polar('f', test_model, [], data_ls, []);
      armijo = (Prediction_after - Prediction_before <=  -1e-4 * stepSize * innerproduct);
      j = 0;
      while ~armijo
          j = j  + 1;
          stepSize = stepSize / 2;
          U = uf(X2.U + stepSize*ProjDir.U);
          V = uf(X2.V + stepSize*ProjDir.V);
          B = L'*expm(L'\(stepSize*ProjDir.B)/L)*L;
          test_model.U = U; test_model.B = B; test_model.V = V; test_model.lambda = lambda;
          Prediction_after = functions_matrix_completion_polar('f', test_model, [], data_ls, []);
          armijo = (Prediction_after - Prediction_before <= 1e-4 * stepSize * innerproduct);
          if j > 10, 
              fprintf('..... Predictor direction is not good. Warm-restart enforced.\n')
              U = X2.U;
              B = X2.B;
              V = X2.V;
              break;
          end
      end
      
       fprintf('..... Prediction:   %.5e, #extra-linesearch %i and stepSize = %.3e \n', Prediction_after, j, stepSize);
else
    U = X2.U;
    B = X2.B;
    V = X2.V;    
end
    
       
end